<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<title>DiscordBotClient - Config Editor</title>
		<style>
			html,
			body,
			#container {
				position: absolute;
				left: 0;
				top: 0;
				width: 100%;
				height: 100%;
				margin: 0;
				padding: 0;
				overflow: hidden;
			}
		</style>
	</head>

	<body>
		<div id="container"></div>
		<script src="https://cdn.jsdelivr.net/npm/monaco-editor@latest/min/vs/loader.js"></script>
		<script>
			require.config({
				paths: {
					vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@latest/min/vs',
				},
			});
			require(['vs/editor/editor.main'], async () => {
				monaco.languages.register({ id: 'ini' });
				const AutoComplete = await window.settingsAPI.getAutoComplete();
				monaco.languages.registerCompletionItemProvider('ini', {
					triggerCharacters: [
						'=',
						'\n',
						...'abcdefghijklmnopqrstuvwxyz0123456789'.split(''),
					],
					provideCompletionItems: function (model, position) {
						const existingKeys = new Set();
						model.getLinesContent().forEach((line) => {
							const m = line.match(/^\s*([a-zA-Z0-9_]+)\s*=/);
							if (m) existingKeys.add(m[1]);
						});
						const textUntilPos = model
							.getValueInRange({
								startLineNumber: position.lineNumber,
								startColumn: 1,
								endLineNumber: position.lineNumber,
								endColumn: position.column,
							})
							.trim();
						const KEYWORDS = Object.entries(AutoComplete).map(
							([key, value]) => ({
								label: key,
								insertText: key + '=',
								kind: monaco.languages.CompletionItemKind
									.Property,
								documentation: {
									value: value.documentation,
									isTrusted: true,
								},
							}),
						);
						const ENUMS = {};
						Object.entries(AutoComplete).forEach(([key, value]) => {
							if (value.enum) {
								ENUMS[key] = Object.entries(value.enum).map(
									([enumKey, enumValue]) => ({
										label: enumKey,
										insertText: enumKey,
										kind: monaco.languages
											.CompletionItemKind.EnumMember,
										documentation: {
											value: enumValue.documentation,
											isTrusted: true,
										},
									}),
								);
							}
						});
						if (
							/^\[.*\]$/.test(textUntilPos) ||
							textUntilPos === ''
						) {
							return {
								suggestions: KEYWORDS.filter(
									(k) => !existingKeys.has(k.label),
								),
							};
						}
						const m = textUntilPos.match(
							/^([a-zA-Z0-9_]+)\s*=\s*([a-zA-Z0-9_]*)$/,
						);
						if (m && ENUMS[m[1]]) {
							return {
								suggestions: ENUMS[m[1]],
							};
						}
						return {
							suggestions: KEYWORDS.filter(
								(k) =>
									!existingKeys.has(k.label) &&
									k.label.includes(textUntilPos),
							),
						};
					},
				});
				monaco.languages.registerHoverProvider('ini', {
					provideHover: function (model, position) {
						const word = model.getWordAtPosition(position);
						if (!word) return;
						if (AutoComplete[word.word]) {
							return {
								range: new monaco.Range(
									position.lineNumber,
									word.startColumn,
									position.lineNumber,
									word.endColumn,
								),
								contents: [
									{
										value: `**${word.word}**: ${
											AutoComplete[word.word]
												.documentation
										}`,
									},
								],
							};
						}
					},
				});

				let content = await window.settingsAPI.getCurrentSettings();

				const editor = monaco.editor.create(
					document.getElementById('container'),
					{
						value: content,
						language: 'ini',
						theme: 'vs-dark',
						quickSuggestions: {
							other: true,
							comments: false,
							strings: true,
						},
						automaticLayout: true,
					},
				);
				editor.onDidChangeModelContent(() => {
					if (editor.getValue() === content) {
						document.title = 'DiscordBotClient - Config Editor';
					} else {
						document.title =
							'DiscordBotClient - Config Editor (Unsaved Changes - Press Ctrl+S to save)';
					}
				});
				// Ctrl+S
				window.addEventListener('keydown', async (e) => {
					if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 's') {
						e.preventDefault();
						await window.settingsAPI.saveCurrentSettings(
							editor.getValue(),
						);
						content = await window.settingsAPI.getCurrentSettings();
						const model = editor.getModel();
						model.pushEditOperations(
							[],
							[
								{
									range: model.getFullModelRange(),
									text: content,
								},
							],
							() => null,
						);
					}
				});
			});
		</script>
	</body>
</html>
